package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.bean.Domain;
import com.ruoyi.common.constant.*;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.*;
import com.ruoyi.common.exception.RegisterProcessingException;
import com.ruoyi.common.utils.CalculatorUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.YiHuoUtils;
import com.ruoyi.common.utils.http.NetworkCheck;
import com.ruoyi.common.utils.modbus.TcpToSerialClient;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.ClassMethodNameUtil;
import com.ruoyi.system.utils.LogUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class SensorDataServiceImpl implements SensorDataService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IMrDeviceService mrDeviceService;

    @Autowired
    private IMrBedService mrBedService;

    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private IMrDeviceAlarmDataService mrDeviceAlarmDataService;

    @Autowired
    private IMrAnalogValueConfigService mrAnalogValueConfigService;

    @Autowired
    private IMrDeviceProtocolConfigurationService mrDeviceProtocolConfigurationService;

    @Autowired
    private IMrMonitorDevicePointValueService mrMonitorDevicePointValueService;

    @Autowired
    private LogUtil logUtil;


    private static final Logger log = LoggerFactory.getLogger(SensorDataServiceImpl.class);

    /**
     * 更新设备状态信息
     *
     * @param port 设备端口
     */
    @Override
    public void updateDeviceStatus(String port) {
        if (StringUtils.isEmpty(port)) {
            log.warn("【updateDeviceStatus】设备端口为空");
            return;
        }

        MrDevice device = mrDeviceService.getDeviceByOutputSource(port);
        if (device == null) {
            log.warn("【updateDeviceStatus】未找到端口[{}]对应的设备", port);
            return;
        }

        // 清除延迟时间缓存
        redisCache.deleteObject(Constants.DELAY_TIME + device.getSystemId());
        redisCache.deleteObject(ConstantsEnum.LAST_WARN_TIME.getValue() + device.getSystemId());

        // 更新设备状态
        updateDeviceWarnStatus(device);

        // 清理告警缓存
        cleanDeviceWarnCache(device);
    }

    /**
     * 更新设备告警状态
     */
    private void updateDeviceWarnStatus(MrDevice device) {
        MrDevice update = new MrDevice();
        update.setDeviceId(device.getDeviceId());
        update.setWarnStatus(DeviceWarnStatus.LINE.getValue());
        update.setLastHeartbeatTime(new Date());
        update.setRemark(Boolean.FALSE.toString());
        mrDeviceService.updateMrDevice(update);
    }

    /**
     * 清理设备告警缓存
     */
    private void cleanDeviceWarnCache(MrDevice device) {
        Map<String, String> devWarnCache = redisCache.getCacheObject(ConstantsEnum.DEV_WARN_CACHE.getValue());
        if (devWarnCache != null && devWarnCache.containsKey(device.getDeviceId().toString())) {
            devWarnCache.remove(device.getDeviceId().toString());
            redisCache.setCacheObject(ConstantsEnum.DEV_WARN_CACHE.getValue(), devWarnCache);
        }
    }

    /**
     * 处理寄存器数据（支持单/双寄存器）
     *
     * @param registerAddress 寄存器地址字符串（格式如"40001"或"40001-40002"）
     * @param startAdd        起始地址
     * @param regisData       寄存器数据列表
     * @param deviceId        设备ID（用于日志）
     * @param jsonObject      原始JSON数据（用于日志）
     * @return 处理后的寄存器值
     * @throws RegisterProcessingException 当处理失败时抛出
     */
    @Override
    public String processRegisterValue(String registerAddress, int startAdd, List<String> regisData, String deviceId, JSONObject jsonObject) throws RegisterProcessingException {
        // 1. 参数校验
        if (registerAddress == null || registerAddress.isEmpty()) {
            throw new RegisterProcessingException("寄存器地址为空", deviceId, jsonObject);
        }
        if (regisData == null) {
            throw new RegisterProcessingException("寄存器数据为空", deviceId, jsonObject);
        }

        // 2. 分割地址
        String[] addresses = registerAddress.split(StringConstants.HYPHEN);

        try {
            // 3. 处理单寄存器
            if (addresses.length == NumberConstants.ONE) {
                return processSingleRegister(addresses[NumberConstants.ZERO], startAdd, regisData, deviceId, jsonObject);
            }
            // 4. 处理双寄存器
            else if (addresses.length == NumberConstants.TWO) {
                return processDualRegisters(addresses[NumberConstants.ZERO], addresses[NumberConstants.ONE], startAdd, regisData, deviceId, jsonObject);
            } else {
                throw new RegisterProcessingException("无效的寄存器地址格式: " + registerAddress, deviceId, jsonObject);
            }
        } catch (NumberFormatException e) {
            throw new RegisterProcessingException("寄存器地址格式错误: " + registerAddress, deviceId, jsonObject, e);
        } catch (IndexOutOfBoundsException e) {
            throw new RegisterProcessingException("寄存器地址超出数据范围", deviceId, jsonObject, e);
        }
    }

    /**
     * 处理单寄存器
     */
    private static String processSingleRegister(String addressStr, int startAdd, List<String> regisData, String deviceId, JSONObject jsonObject) throws RegisterProcessingException {
        int address = Integer.parseInt(addressStr);
        int relativeAddr = address - startAdd;

        // 地址校验
        if (relativeAddr < NumberConstants.ZERO) {
            throw new RegisterProcessingException(String.format("寄存器地址(%d)小于起始地址(%d)", address, startAdd), deviceId, jsonObject);
        }
        if (relativeAddr >= regisData.size()) {
            throw new RegisterProcessingException(String.format("寄存器地址(%d)超出数据范围(%d)", address, regisData.size()), deviceId, jsonObject);
        }

        // 获取寄存器值
        return regisData.get(relativeAddr);
    }

    /**
     * 处理双寄存器
     */
    private static String processDualRegisters(String addr1Str, String addr2Str, int startAdd, List<String> regisData, String deviceId, JSONObject jsonObject) throws RegisterProcessingException {
        int addr1 = Integer.parseInt(addr1Str);
        int addr2 = Integer.parseInt(addr2Str);
        int relativeAddr1 = addr1 - startAdd;
        int relativeAddr2 = addr2 - startAdd;

        // 地址校验
        if (relativeAddr1 < NumberConstants.ZERO || relativeAddr2 < NumberConstants.ZERO) {
            throw new RegisterProcessingException(String.format("双寄存器地址(%d-%d)小于起始地址(%d)", addr1, addr2, startAdd), deviceId, jsonObject);
        }
        if (relativeAddr1 >= regisData.size() || relativeAddr2 >= regisData.size()) {
            throw new RegisterProcessingException(String.format("双寄存器地址(%d-%d)超出数据范围(%d)", addr1, addr2, regisData.size()), deviceId, jsonObject);
        }

        // 获取并组合双寄存器值
        String value1 = Long.toHexString(Long.parseLong(regisData.get(relativeAddr2)));
        String value2 = Long.toHexString(Long.parseLong(regisData.get(relativeAddr1)));
        String combinedValue = value1 + value2;

        // 转换为十进制
        return String.valueOf(new BigInteger(combinedValue, NumberConstants.SIXTEEN).intValue());
    }

    /**
     * 校验设备数据参数是否有效
     *
     * @param regisData  寄存器数据
     * @param startAdd   起始地址
     * @param device     设备对象
     * @param jsonObject 原始JSON数据
     * @return true-参数有效，false-参数无效
     */
    @Override
    public boolean validateDeviceParameters(List<String> regisData, Integer startAdd, MrDevice device, JSONObject jsonObject) {
        if (regisData == null) {
            log.warn("【dataUpload】网关设备上行无数据：{}", jsonObject);
            return false;
        }

        if (startAdd == null) {
            log.warn("【dataUpload】网关设备上行无起始地址，网关报文：{}", jsonObject);
            return false;
        }

        if (StringUtils.isEmpty(device.getModality())) {
            log.warn("【dataUpload】设备类型未配置，设备systemId：{}", device.getSystemId());
            return false;
        }

        if (StringUtils.isEmpty(device.getProduct())) {
            log.warn("【dataUpload】设备型号未配置，设备systemId：{}", device.getSystemId());
            return false;
        }

        if (StringUtils.isEmpty(device.getRegisterAddress())) {
//            log.warn("【dataUpload】寄存器地址未配置，设备systemId：{}", device.getSystemId());
            return false;
        }

        if (ProductEnum.TYPE_DEVICE.getValue().equals(device.getProduct()) && StringUtils.isEmpty(device.getSwitchingPosition())) {
            log.warn("【dataUpload】开关量位未配置，设备systemId：{}", device.getSystemId());
            return false;
        }

        if (ProductEnum.TYPE_HXALA.getValue().equals(device.getProduct()) && StringUtils.isEmpty(device.getSwitchingPosition())) {
            log.warn("【dataUpload】开关量位未配置，设备systemId：{}", device.getSystemId());
            return false;
        }

        // 读写锁判断
        if (redisCache.hasKey(CacheConstants.DEV_WRITE_LOCK + device.getSystemId())) {
            if (redisCache.getCacheObject(CacheConstants.DEV_WRITE_LOCK + device.getSystemId())) {
                return false;
            }
        }


        return true;
    }

    /**
     * 检查设备是否需要跳过处理（基于延时时间配置）
     *
     * @param device    设备对象
     * @param delayTime 默认延时时间
     * @return true-需要跳过处理，false-不需要跳过
     */
    @Override
    public boolean shouldSkipByDelayTime(MrDevice device, int delayTime) {
        // 获取延时时间配置
        delayTime = StringUtils.isNotEmpty(device.getDelayTime()) ? Integer.parseInt(device.getDelayTime()) : delayTime;

        // 如果设备没有最后心跳时间或延时时间为0，则不需要跳过
        if (device.getLastHeartbeatTime() == null || delayTime == NumberConstants.ZERO) {
            return false;
        }

        String warnTimeKey = ConstantsEnum.LAST_WARN_TIME.getValue() + device.getSystemId();

        // 如果没有警告时间记录且延时时间不为0，则记录当前时间并跳过
        if (!redisCache.hasKey(warnTimeKey)) {
            redisCache.setCacheObject(warnTimeKey, System.currentTimeMillis());
            return true;
        }

        // 计算时间差（秒）
        long timeDifferenceSec = (System.currentTimeMillis() - getLastWarnTime(device.getSystemId())) / NumberConstants.ONE_THOUSAND;

        // 如果时间差小于延时时间，则跳过处理
        return timeDifferenceSec < delayTime;
    }

    /**
     * 处理数据，包括保存网关上行数据、保存设备报警信息和更新设备状态信息
     *
     * @param mrMonitorDevicePointValues 网关上行数据列表
     * @param mrDeviceAlarmDatas         设备报警信息列表
     * @param mrDeviceList               设备状态信息列表
     */
    @Override
    public void gatewayBatchData(List<MrMonitorDevicePointValue> mrMonitorDevicePointValues, List<MrDeviceAlarmData> mrDeviceAlarmDatas, List<MrDevice> mrDeviceList) {
        // 保存网关上行数据
//        if (!mrMonitorDevicePointValues.isEmpty()) {
//            mrMonitorDevicePointValueService.bathInsertMrMonitorDevicePointValue(mrMonitorDevicePointValues);
//        }
        // 保存设备报警信息
        if (!mrDeviceAlarmDatas.isEmpty()) {
            mrDeviceAlarmDataService.insertBatch(mrDeviceAlarmDatas);
        }
        // 更新设备状态信息
//        if (!mrDeviceList.isEmpty()){
//            mrDeviceService.bathUpdateMrDevice(mrDeviceList);
//        }
    }

    /**
     * 处理 非零报警 协议的数据
     *
     * @param value 设备数据
     * @return 处理后的值
     */
    public String processNonZeroAlarmData(String value) {
        String result = value;
        if (StringUtils.isNotEmpty(value) && !DigitStringConstants.ZERO.equals(value)) {
            value = DigitStringConstants.ONE;
        }
        String msg = "【dataUpload】【processNonZeroAlarmData】非零报警协议入参：" + result + ", 结果：" + value;
        logUtil.info(ClassMethodNameUtil.getSimpleMethodName(), msg);
        return value;
    }


    /**
     * 处理 HXALA 协议的数据
     *
     * @param mr 包含产品信息的对象
     * @return 处理后的值
     */
    public String processHXALAData(MrDevice mr) {
        String value = null;
        String responseData = mr.getRegisData();
        if (StringUtils.isEmpty(responseData)) {
            responseData = TcpToSerialClient.getData(mr.getHost(), Integer.parseInt(mr.getPort()));
        }
        String msg = "【dataUpload】【processHXALAData】HXALA协议报文：" + responseData;
        logUtil.info(ClassMethodNameUtil.getSimpleMethodName(), msg);
        if (StringUtils.isNotEmpty(responseData)) {
            if (isCheckValid(responseData)) {
                value = processHXALAData(responseData, mr);
            } else {
                log.warn("【dataUpload】【processHXALAData】HXALA异或校验失败，报文：{}", responseData);
            }
        } else {
            log.warn("【dataUpload】【processHXALAData】HXALA报文为空，报文：{}", responseData);
        }
        return value;
    }

    /**
     * 处理 XDR 协议的数据
     *
     * @param mr 包含产品信息的对象
     * @return 处理后的值
     */
    @Override
    public String processXdrData(MrDevice mr) {
        String value = null;
        String responseData = mr.getRegisData();
        if (StringUtils.isEmpty(responseData)) {
            responseData = TcpToSerialClient.getData(mr.getHost(), Integer.parseInt(mr.getPort()));
        }
        String msg = "【dataUpload】【processXdrData】XDR协议报文：" + responseData;
        logUtil.info(ClassMethodNameUtil.getSimpleMethodName(), msg);
        if (StringUtils.isNotEmpty(responseData)) {
            if (isCheckValid(responseData)) {
                value = parseXdrData(responseData, mr);
            } else {
                log.warn("【dataUpload】【processXdrData】XDR异或校验失败，报文：{}", responseData);
            }
        } else {
            log.warn("【dataUpload】【processXdrData】XDR报文为空，报文：{}", responseData);
        }
        return value;
    }

    /**
     * 处理 LDAXDR 协议的数据
     * 自动舵的报警板VDR实测数据
     * $LDAXDR,0000,0000,*2B    (解读:所有各点全无报警）
     * $LDAXDR,0102,1300,*2A    (解读:X2为1是1#电源、X4为2是2#断相、X5为1是1#液压阻塞、X6为3是1#失油压、2#失油压,其他各点都没有报警和显示）
     *
     * @param mr 包含产品信息的对象
     * @return 处理后的值
     */
    @Override
    public String processLdaxdrData(MrDevice mr) {
        String value = null;
        String responseData = mr.getRegisData();
        if (StringUtils.isEmpty(responseData)) {
            responseData = TcpToSerialClient.getData(mr.getHost(), Integer.parseInt(mr.getPort()));
        }
        String msg = "【dataUpload】【processLdaxdrData】LDAXDR协议报文：" + responseData;
        logUtil.info(ClassMethodNameUtil.getSimpleMethodName(), msg);
        if (StringUtils.isNotEmpty(responseData)) {
            if (isCheckValid(responseData)) {
                value = parseLdaxdrData(responseData, mr);
            } else {
                log.warn("【dataUpload】LDAXDR异或校验失败，报文：{}", responseData);
            }
        } else {
            log.warn("【dataUpload】LDAXDR报文为空，报文：{}", responseData);
        }
        return value;
    }

    /**
     * 处理设备开关相关数据
     *
     * @param mr    包含设备信息的对象
     * @param value 设备数据
     * @return 处理后的值
     */
    @Override
    public String processDeviceSwitchData(MrDevice mr, String value) {
        if (value != null) {
            // 调用 getChars 方法将值转换为字符数组
            char[] chars = getChars(value);
            // 根据开关位置获取对应的值
            value = String.valueOf(chars[Integer.parseInt(mr.getSwitchingPosition())]);
        }
        return value;
    }

    /**
     * 处理 字段配置 模拟量的数据
     * 需配置模拟量值定义配置表
     *
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    public String processConfigurationData(MrDevice mr, String value) {
        if (value != null) {
            MrAnalogValueConfig mrAnalogValueConfig = mrAnalogValueConfigService.selectMrAnalogValueConfigBySystemIdAndAnalogValue(mr.getSystemId(), Long.valueOf(value));
            if (mrAnalogValueConfig != null) {
                value = mrAnalogValueConfig.getCorrespondingName();
                MrDevice mrDevice = new MrDevice();
                mrDevice.setDeviceId(mr.getDeviceId());
                mrDevice.setRemark(value);
                mrDevice.setLightColor(mrAnalogValueConfig.getDisplayColor());
                mrDevice.setDisplayAlarm(mrAnalogValueConfig.getDisplayOrAlarm());
                mrDeviceService.updateMrDevice(mrDevice);
            } else {
                log.warn("【dataUpload】【processConfigurationData】模拟量值定义配置对象 mr_analog_value_config配置信息为空，systemId:{},value:{}", mr.getSystemId(), value);
            }
        }
        return value;
    }

    /**
     * 处理 0183 - VDR 协议的数据
     * $SBMT,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,xxxx,xxxx,xxxx,xxxx,xxx,<CR><LF>
     * $SBMTM,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0000,0000,0000,0053,0000*70\r\n
     * 0 =30H; 1 =31H; 2 =32H
     * 1 控制位置 =30H 驾驶室遥控，=31H 集控室遥控，=32H 机旁控制
     * 2 操纵器手柄位置 =30H 停车位置，=31H 正车位置，=32H 倒车位置
     * 3 控制输出 =30H 停车 =31H 正车 =32H 倒车
     * 4 齿轮箱工作状态 =30H 停车位置，=31H 正车位置，=32H 倒车位置
     * 5 =30H 正常 =31H 故障停车
     * 6 =30H 正常 =31H 故障降速
     * 7 =30H 正常 =31H 应急停车
     * 8 =30H 正常 =31H 应急操纵
     * 9 =30H 正常 =31H 超速
     * 10=30H 正常 =31H 失速
     * 11=30H 正常 =31H 操纵器故障
     * 12=30H 正常 =31H 测速传感器故障
     * 13=30H 正常 =31H 错向报警
     * 14=30H 正常 =31H 失气/失电报警
     * 15 备用
     * 16 操纵器命令转速 4 个 ASCII 数字字符
     * 17 主机实际转速反馈 4 个 ASCII 数字字符
     * 18 尾轴实际转速反馈 4 个 ASCII 数字字符
     * 19 转速控制输出 4 个 ASCII 数字字符
     * 20 备用 4 个 ASCII 数字字符
     * 无通讯认为遥控系统计算机不工作或故障
     *
     * @param mr 包含设备信息的对象
     * @return 处理后的值
     */
    @Override
    public String process0183VdrData(MrDevice mr) {
        String value = null;
        String responseData = mr.getRegisData();
        if (StringUtils.isEmpty(responseData)) {
            responseData = TcpToSerialClient.getData(mr.getHost(), Integer.parseInt(mr.getPort()));
        }
        String msg = "【dataUpload】【process0183VdrData】0183-vdr协议报文：" + responseData;
        logUtil.info(ClassMethodNameUtil.getSimpleMethodName(), msg);
        if (StringUtils.isNotEmpty(responseData)) {
            responseData = responseData.replace("\n", "");
            responseData = responseData.replace("\r", "");
            if (isCheckValid(responseData)) {
                String[] datas = responseData.split("\\$");
                for (String data : datas) {
                    if (StringUtils.isEmpty(data)) {
                        continue;
                    }
                    String[] temStrings = data.split("\\*");
                    String[] strings1 = temStrings[0].split(",");
                    int num = Integer.parseInt(mr.getRegisterAddress());
                    if (StringUtils.isNotEmpty(strings1) && strings1.length > num) {
                        // 模拟量直接获取
                        if (mr.getModality().equals(ProductEnum.BA.getValue())) {
                            value = strings1[num];
                        }
                        // 开关量判断
                        if (mr.getModality().equals(ProductEnum.MR.getValue())) {
                            if (StringUtils.isNotEmpty(mr.getSaveValue()) && strings1[num].contains(mr.getSaveValue())) {
                                value = DigitStringConstants.ONE;
                            } else {
                                value = DigitStringConstants.ZERO;
                            }
                        }
                    }
                }
            } else {
                log.warn("【dataUpload】【process0183VdrData】0183-vdr异或校验失败，报文：{}", responseData);
            }
        } else {
            log.warn("【dataUpload】【process0183VdrData】0183-vdr报文为空，报文：{}", responseData);
        }
        return value;
    }

    /**
     * 处理 0183 协议的数据
     * 协议示例：
     * $PSGA,2,1,A,0,0,0,0,0,1,0,0,0,0,0,0,0*76
     * $PSGA,2,2,B,1,0,0,0,0,0,0,0,0,0,0,0,0*76
     *
     * @param mr 包含设备信息的对象
     * @return 处理后的值，如果符合条件返回 "true"，否则返回 null
     */
    @Override
    public String process0183Data(MrDevice mr) {
        String value = null;
        if (mr.getProduct().equals(ProductEnum.TYPE_0183.getValue())) {
            String responseData = mr.getRegisData();
            if (StringUtils.isEmpty(responseData)) {
                responseData = TcpToSerialClient.getData(mr.getHost(), Integer.parseInt(mr.getPort()));
            }
            String msg = "【dataUpload】【process0183Data】0183协议报文：" + responseData;
            logUtil.info(ClassMethodNameUtil.getSimpleMethodName(), msg);
            if (StringUtils.isNotEmpty(responseData)) {
                responseData = responseData.replace("\n", "");
                responseData = responseData.replace("\r", "");
                if (isCheckValid(responseData)) {
                    value = parseData(responseData, mr);
                } else {
                    log.warn("【dataUpload】0183异或校验失败，报文：{}", responseData);
                }
            } else {
                log.warn("【dataUpload】0183报文为空，报文：{}", responseData);
            }
        }
        return value;
    }

    /**
     * 处理 Modbus 协议的数据
     *
     * @param mr    包含设备信息的对象
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    @Override
    public String processModbusData(MrDevice mr, String value) {
        if (value != null) {
            // 第一步：将值四舍五入保留三位小数
            BigDecimal roundedResult = BigDecimal.valueOf(Double.parseDouble(value)).setScale(3, RoundingMode.HALF_UP);
            // 第二步：根据 symbol 进行判断和处理
            if (StringUtils.isNotEmpty(mr.getSymbol())) {
                if (Double.parseDouble(value) >= NumberConstants.THIRTY_TWO_THOUSAND_SEVEN_HUNDRED_SIXTY_EIGHT) {
                    roundedResult = BigDecimal.valueOf(roundedResult.intValue() - NumberConstants.SIXTY_FIVE_THOUSAND_FIVE_HUNDRED_THIRTY_SIX);
                }
            }
            value = roundedResult.toString();
            // 第三步：根据 multiplyCoefficient 进行系数计算
            if (StringUtils.isNotEmpty(mr.getMultiplyCoefficient())) {
                if (mr.getMultiplyCoefficient().contains("x")) {
                    value = CalculatorUtils.calculateWithExp4j(mr.getMultiplyCoefficient(), Double.parseDouble(value));
                } else {
                    value = CalculatorUtils.calculateWithExp4j("x*" + mr.getMultiplyCoefficient(), Double.parseDouble(value));
                }
            }
            // 第四步：再次将结果四舍五入保留三位小数
            value = BigDecimal.valueOf(Double.parseDouble(value)).setScale(NumberConstants.THREE, RoundingMode.HALF_UP).toString();
        }
        return value;
    }

    /**
     * 处理 Modbus 浮点采集协议的数据
     *
     * @param mr    包含设备信息的对象
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    public String processModbusFloatData(MrDevice mr, String value) {
        if (mr.getStartAdd() != null && !mr.getRegisDatas().isEmpty()) {
            int num = Integer.parseInt(mr.getRegisterAddress()) - mr.getStartAdd();
            int high = Integer.parseInt(mr.getRegisDatas().get(num));
            int low = Integer.parseInt(mr.getRegisDatas().get(num + 1));
            float valueFloat = convertToFloat(high, low);
            // 第一步：将值四舍五入保留三位小数
            BigDecimal roundedResult = BigDecimal.valueOf(valueFloat).setScale(3, RoundingMode.HALF_UP);
            value = roundedResult.toString();
        }
        return value;
    }

    /**
     * 将两个16位寄存器转换为浮点数
     */
    public static float convertToFloat(int high, int low) {
        int intValue = (high << 16) | low;
        return Float.intBitsToFloat(intValue);
    }

    /**
     * 处理硬接点模块的数据
     *
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    @Override
    public String processHardContactModuleData(String value) {
        if (value != null) {
            // 将值乘以 0.001 并四舍五入保留三位小数
            BigDecimal roundedResult = BigDecimal.valueOf(Double.parseDouble(value) * NumberConstants.DECIMAL_POINT_ZERO_ZERO_ONE).setScale(NumberConstants.THREE, RoundingMode.HALF_UP);
            value = roundedResult.toString();
        }
        return value;
    }

    /**
     * 处理 0 - 30V 电压采样模块的数据
     * 0-30V电压采样模块解析方法是先16进制数转换成10进制后，最前面的数代表小数点位数，有效数据4位，
     * （1）比如21823，读成18.23V
     * （2）比如31023，读成1.023V
     * （3）比如43152，读成0.3152V
     * 注：第1位代表小数点的只可能是2、3、4这3个数，其他的数不可能能出现
     *
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    @Override
    public String processVoltageSamplingModuleData(String value) {
        if (value != null) {
            if (value.length() == NumberConstants.FIVE) {
                String str = value.substring(NumberConstants.ONE, NumberConstants.FIVE);
                String strNum = value.substring(NumberConstants.ZERO, NumberConstants.ONE);
                long longNum = Long.parseLong(str);
                double result;
                switch (strNum) {
                    case DigitStringConstants.TWO:
                        result = (double) longNum / NumberConstants.ONE_HUNDRED;
                        break;
                    case DigitStringConstants.THREE:
                        result = (double) longNum / NumberConstants.ONE_THOUSAND;
                        break;
                    case DigitStringConstants.FOUR:
                        result = (double) longNum / NumberConstants.TEN_THOUSAND;
                        break;
                    default:
                        // 若出现不符合规则的第一位数字，可根据实际需求处理，这里简单返回原数据
                        return value;
                }
                BigDecimal roundedResult = BigDecimal.valueOf(result).setScale(NumberConstants.THREE, RoundingMode.HALF_UP);
                value = roundedResult.toString();
            }
        }
        return value;
    }

    /**
     * 处理 PT100 设备的数据
     *
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    @Override
    public String processPt100Data(String value) {
        BigDecimal roundedResult = null;
        double doubleValue = Double.parseDouble(value);
        if (doubleValue >= NumberConstants.THIRTY_TWO_THOUSAND_SEVEN_HUNDRED_SIXTY_EIGHT) {
            roundedResult = BigDecimal.valueOf((NumberConstants.THIRTY_TWO_THOUSAND_SEVEN_HUNDRED_SIXTY_EIGHT - doubleValue) * NumberConstants.DECIMAL_POINT_ONE).setScale(NumberConstants.THREE, RoundingMode.HALF_UP);
        }
        if (roundedResult != null) {
            return roundedResult.toString();
        }
        value = BigDecimal.valueOf(doubleValue * NumberConstants.DECIMAL_POINT_ONE).setScale(NumberConstants.THREE, RoundingMode.HALF_UP).toString();
        return value;
    }

    /**
     * 处理 4 - 20mA 输出设备的数据
     *
     * @param mr    包含设备信息的对象
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    @Override
    public String processFourToTwentyMaOutputData(MrDevice mr, String value) {
        if (mr.getProduct().equals(ProductEnum.TYPE_4_20_MA_OUTPUT.getValue())) {
            if (StringUtils.isNotEmpty(mr.getOutputRange()) && value != null) {
                BigDecimal roundedResult = BigDecimal.valueOf(
                        (
                                ((Double.parseDouble(value) / NumberConstants.ONE_THOUSAND) - NumberConstants.FOUR)
                                        * (Double.parseDouble(mr.getOutputRange()) / NumberConstants.SIXTEEN)
                        )
                ).setScale(NumberConstants.THREE, RoundingMode.HALF_UP);
                value = roundedResult.toString();
            }
        }
        return value;
    }

    /**
     * 处理 4 - 20mA 设备的数据
     *
     * @param mr    包含设备信息的对象
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    @Override
    public String processFourToTwentyMaData(MrDevice mr, String value) {
        if (mr.getProduct().equals(ProductEnum.TYPE_4_20_MA.getValue()) && value.length() == NumberConstants.FIVE) {
            String str = value.substring(NumberConstants.ONE, NumberConstants.FIVE);
            long longNum = Long.parseLong(str);
            double result = (double) longNum / NumberConstants.TWO_HUNDRED_FORTY_NINE;
            BigDecimal roundedResult = BigDecimal.valueOf(result).setScale(3, RoundingMode.HALF_UP);
            BigDecimal temp = roundedResult;

            if (StringUtils.isNotEmpty(mr.getInputRange())) {
                roundedResult = BigDecimal.valueOf((Float.parseFloat(roundedResult.toString()) - NumberConstants.FOUR) * Float.parseFloat(mr.getInputRange()) / NumberConstants.SIXTEEN).setScale(NumberConstants.THREE, RoundingMode.HALF_UP);
            }

            if (StringUtils.isNotEmpty(mr.getDataStartPosition()) && temp.compareTo(new BigDecimal(DigitStringConstants.FOUR_POINT_ZERO_ZERO_FIVE)) > NumberConstants.ZERO) {
                roundedResult = roundedResult.add(new BigDecimal(mr.getDataStartPosition()));
            }

            value = roundedResult.toString();
        }
        return value;
    }

    /**
     * 处理不同模式和产品类型的数据
     *
     * @param mr    包含设备信息的对象
     * @param value 原始数据值
     * @return 处理后的数据值
     */
    @Override
    public String processData(MrDevice mr, String value) {
        // 模拟量处理
        if (mr.getModality().equals(ProductEnum.BA.getValue())) {
            if (mr.getProduct().equals(ProductEnum.TYPE_4_20_MA.getValue())) {
                value = processFourToTwentyMaData(mr, value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_4_20_MA_OUTPUT.getValue())) {
                value = processFourToTwentyMaOutputData(mr, value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_PT100.getValue())) {
                value = processPt100Data(value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_0_10_V.getValue())) {
                value = processVoltageSamplingModuleData(value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_HARD_CONTACT_MODULE.getValue())) {
                value = processHardContactModuleData(value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_MODBUS.getValue())) {
                value = processModbusData(mr, value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_0183_VDR.getValue())) {
                value = process0183VdrData(mr);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_CONFIGURATION.getValue())) {
                value = processConfigurationData(mr, value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_MODBUS_FLOAT.getValue())) {
                value = processModbusFloatData(mr, value);
            }
        } else if (mr.getModality().equals(ProductEnum.MR.getValue())) {
            // 开关量处理
            if (mr.getProduct().equals(ProductEnum.TYPE_MR_A_0.getValue())) {
                value = value;
            } else if (mr.getProduct().equals(ProductEnum.TYPE_0183.getValue())) {
                value = process0183Data(mr);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_0183_VDR.getValue())) {
                value = process0183VdrData(mr);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_DEVICE.getValue())) {
                value = processDeviceSwitchData(mr, value);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_LDAXDR.getValue())) {
                value = processLdaxdrData(mr);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_XDR.getValue())) {
                value = processXdrData(mr);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_HXALA.getValue())) {
                value = processHXALAData(mr);
            } else if (mr.getProduct().equals(ProductEnum.TYPE_NON_ZERO_ALARM.getValue())) {
                value = processNonZeroAlarmData(value);
            }
        }
        return value;
    }

    /**
     * 处理功能码并设置 MrDevice 的相关属性
     *
     * @param jsonObject 包含设备信息的 JSON 对象
     * @param mrDevice   设备信息对象
     */
    @Override
    public void processFunctionCode(JSONObject jsonObject, MrDevice mrDevice) {
        if (!configService.selectFunctionCode()) {
            return;
        }
        if (jsonObject.containsKey(ConstantsEnum.FUN_CODE.getValue())) {
            int funCodeValue = jsonObject.getIntValue(ConstantsEnum.FUN_CODE.getValue());
            if (ModbusFunctionCode.READ_DISCRETE_INPUTS.getCode() == funCodeValue) {
                // 开关量
                mrDevice.setModality(ProductEnum.MR.getValue());
            } else if (ModbusFunctionCode.READ_INPUT_REGISTERS.getCode() == funCodeValue) {
                // 模拟量
                mrDevice.setModality(ProductEnum.BA.getValue());
            }
        }
        if (jsonObject.containsKey(ConstantsEnum.GATEWAY_IP.getValue())) {
            mrDevice.setHost(jsonObject.getString(ConstantsEnum.GATEWAY_IP.getValue()));
        }
    }

    @Override
    public boolean checkConnect() {
        if (configService.selectDataEnabled()) {
            return false;
        } else {
            return NetworkCheck.checkConnect(ConstantsEnum.SERVER_124.getValue());
        }
    }

    /**
     * 解析数据，判断是否符合条件
     *
     * @param responseData 响应数据
     * @param mr           包含设备信息的对象
     * @return 符合条件返回 "true"，否则返回 null
     */
    private String parseData(String responseData, MrDevice mr) {
        String value = null;
        String[] datas = responseData.split("\\$");
        for (String data : datas) {
            if (StringUtils.isEmpty(data)) {
                continue;
            }
            String[] temStrings = data.split("\\*");
            String[] strings1 = temStrings[0].split(",");
            int num = Integer.parseInt(mr.getRegisterAddress()) + NumberConstants.FOUR;
            if (strings1.length > num) {
                if (StringUtils.isNotEmpty(strings1) && strings1[3].equals(mr.getSymbol()) && strings1[num].contains(DigitStringConstants.ONE)) {
                    value = DigitStringConstants.ONE;
                } else {
                    value = DigitStringConstants.ZERO;
                }
            }
        }
        return value;
    }

    /**
     * 解析 LDAXDR 数据
     *
     * @param responseData 响应数据
     * @param mr           包含产品信息的对象
     * @return 解析后的值
     */
    private String parseLdaxdrData(String responseData, MrDevice mr) {
        String value = null;
        String[] datas = responseData.split("\\$");
        for (String data : datas) {
            if (StringUtils.isEmpty(data)) {
                continue;
            }
            String[] temStrings = data.split("\\*");
            String[] strings1 = temStrings[0].split(",");
            if (StringUtils.isNotEmpty(strings1)) {
                String dataString = strings1[1] + strings1[2];
                int num = Integer.parseInt(mr.getRegisterAddress()) - NumberConstants.ONE;
                if (dataString.length() > num) {
                    String hexString = dataString.substring(num, Integer.parseInt(mr.getRegisterAddress()));
                    int decimal = Integer.parseInt(hexString, NumberConstants.SIXTEEN);
                    String binaryNumber = Integer.toBinaryString(decimal);
                    char[] chars = getChars(binaryNumber);
                    value = String.valueOf(chars[Integer.parseInt(mr.getSwitchingPosition())]);
                }
            }
        }
        return value;
    }

    /**
     * 验证 XDR 数据的异或校验是否通过
     *
     * @param responseData 响应数据
     * @return 校验是否通过
     */
    private boolean isCheckValid(String responseData) {
        String[] datas = responseData.split("\\$");
        for (String data : datas) {
            if (StringUtils.isEmpty(data)) {
                continue;
            }
            String[] temStrings = data.split("\\*");
            if (temStrings.length == 1) {
                return false;
            }
            String result1 = YiHuoUtils.yiHuo(temStrings[0]);
            String result2 = temStrings[1].toLowerCase();
            if (result1 != null) {
                result1 = result1.trim();
            }
            result2 = result2.trim();
            if (result1 == null || !Objects.equals(result1, result2)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 解析 XDR 数据
     * 数据示例：
     * $--XDR,S,0,,0,S,0,,1,S,0,,2,S,1,,3,S,1,,4,S,0,,5,S,1,,6,S,1,,7,S,1,,8,S,1,,9,S,0,,10,S,1,,11,S,1,,12,S,1,,13,S,1,,14,S,1,,15,S,0,,16,S,1,,17,S,1,,18,S,1,,19,S,0,,20,S,1,,21,S,1,,22,S,1,,23,S,0,,24,S,0,,25*4E
     *
     * $ZHXDR,S,0,,0,S,0,,1,S,0,,2,S,0,,3,S,0,,4,S,0,,5,S,0,,6,S,0,,7*5C
     * $ZHXDR,S,0,,8,S,0,,9,S,0,,10,S,0,,11,S,0,,12,S,0,,13,S,0,,14,S,0,,15*5C
     * $ZHXDR,S,0,,16,S,0,,17,S,0,,18,S,0,,19,S,0,,20,S,0,,21,S,0,,22,S,0,,23*5C
     * $ZHXDR,S,0,,24,S,1,,25*5C
     *
     * @param responseData 响应数据
     * @param mr           包含产品信息的对象
     * @return 解析后的值
     */
    private String parseXdrData(String responseData, MrDevice mr) {
        String value = null;
        String[] datas = responseData.split("\\$");
        for (String data : datas) {
            if (StringUtils.isEmpty(data)) {
                continue;
            }
            String[] temStrings = data.split("\\*");
            String[] strings1 = temStrings[0].split("S");
            for (String str : strings1) {
                String[] temDatas = str.split(",");
                if (temDatas.length < 3) {
                    continue;
                }
                String num = temDatas[3];
                if (num.equals(mr.getRegisterAddress())) {
                    if (StringUtils.isNotEmpty(temDatas) && temDatas[1].contains(DigitStringConstants.ONE)) {
                        value = DigitStringConstants.ONE;
                    } else {
                        value = DigitStringConstants.ZERO;
                    }
                }
            }
        }
        return value;
    }

    /**
     * 解析 HXALA 数据
     * 数据示例：
     * $HXALA,1#HXXXXXXXXX,2#HXXXXXXXXX*CC
     * $HXALA,1#----------,2#R---1-----*3C
     *
     * @param responseData 响应数据
     * @param mr           包含产品信息的对象
     * @return 解析后的值
     */
    private String processHXALAData(String responseData, MrDevice mr) {
        String value = null;
        String[] datas = responseData.split("\\$");
        for (String data : datas) {
            if (StringUtils.isEmpty(data)) {
                continue;
            }
            String[] temStrings = data.split("\\*");
            String[] strings1 = temStrings[0].split(",");
            if ((Integer.parseInt(mr.getSwitchingPosition()) + NumberConstants.ONE) > strings1.length) {
                continue;
            }
            String stringDatas = strings1[Integer.parseInt(mr.getSwitchingPosition())];
            int num = Integer.parseInt(mr.getRegisterAddress()) + NumberConstants.TWO;
            if (num > stringDatas.length()) {
                continue;
            }
            char ch = stringDatas.charAt(num);
            // H:  电动机运行信号输出为‘R’运行 ，输出为‘-’停止
            // X:  输出为‘1’有报警，输出为‘-’ 无报警
            if (DigitStringConstants.ZERO.contains(mr.getRegisterAddress())) {
                if (ch == 'R') {
                    value = DigitStringConstants.ONE;
                } else {
                    value = DigitStringConstants.ZERO;
                }
            } else {
                if (ch == '1') {
                    value = DigitStringConstants.ONE;
                } else {
                    value = DigitStringConstants.ZERO;
                }
            }
        }
        return value;
    }

    @Override
    public long getLastWarnTime(String systemId) {
        if (!redisCache.hasKey(ConstantsEnum.LAST_WARN_TIME + systemId)) {
            // 记录报警时间
            redisCache.setCacheObject(ConstantsEnum.LAST_WARN_TIME + systemId, new Date().getTime());
        }
        Long lastWarnTime = redisCache.getCacheObject(ConstantsEnum.LAST_WARN_TIME.getValue() + systemId);
        if (lastWarnTime == null || lastWarnTime == 0L) {
            lastWarnTime = new Date().getTime() - 1200000;
        }
        return lastWarnTime;
    }

    @Override
    public void marineEngineer(String systemId, String type) {
        String outputSource = MaritimeConstants.MARINE_ENGINEER;
        MrDevice mr = mrDeviceService.getDeviceByOutputSource(outputSource);
        if (mr == null) {
            log.error("【marineEngineer】轮机员无数据");
            return;
        }
        String systemId2 = null;
        String systemId3 = mr.getSystemId();
        String marine_engineer_status = ConstantsEnum.MARINE_ENGINEER_STATUS.getValue();
        List<SysDictData> sysDictDatas = sysDictDataService.selectDictDataByType(ConstantsEnum.ALARM_SHIELDING.getValue());
        for (SysDictData sysDictData : sysDictDatas) {
            if (Constants.SILENCING.equals(sysDictData.getDictLabel())) {
                systemId2 = sysDictData.getDictValue();
                continue;
            }
            if (systemId.equals(sysDictData.getDictValue())) {
                return;
            }
        }
        if (systemId2 == null) {
            log.error("【marineEngineer】未配置消音按钮字典");
            return;
        }
        if (!redisCache.hasKey(marine_engineer_status)) {
            return;
        }
        if (redisCache.getCacheObject(marine_engineer_status)) {
            if (systemId.equals(systemId2)) {
                redisCache.setCacheObject(marine_engineer_status, false);
                redisCache.deleteObject(systemId3);
                // 报警轮机员输出
                mrDeviceService.mute(false, outputSource);
            } else {
                if (redisCache.hasKey(systemId3)) {
                    Long startTime = redisCache.getCacheObject(systemId3);
                    Long endTime = System.currentTimeMillis();
                    // 延时时间
                    int delayTime = NumberConstants.ONE_HUNDRED_EIGHTY;
                    if (StringUtils.isNotEmpty(mr.getDelayTime())) {
                        delayTime = Integer.parseInt(mr.getDelayTime());
                    }
                    if ((endTime - startTime) / NumberConstants.ONE_THOUSAND > delayTime) {
                        // 报警轮机员输出
                        mrDeviceService.mute(true, outputSource);
                    }
                } else {
                    redisCache.setCacheObject(systemId3, System.currentTimeMillis());
                }

            }
        }

    }

    @Override
    public void associatedAlarm(String systemId, boolean flag) {
        if (systemId == null) {
            return;
        }
        MrDevice mrDevice = mrDeviceService.getDeviceBySystemId(systemId);
        if (mrDevice == null) {
            return;
        }
        MrDevice update = new MrDevice();
        update.setDeviceId(mrDevice.getDeviceId());
        update.setLastHeartbeatTime(new Date());
        if (!flag) {
            MrDevice device = new MrDevice();
            device.setStatus(DeviceStatus.ACTIVE.getValue());
            device.setWarnStatus(DeviceWarnStatus.ALARM.getValue());
            device.setAssociateInternalParameters(systemId);
            List<MrDevice> deviceList = mrDeviceService.selectMrDeviceList(device);
            if (deviceList != null) {
                deviceList = deviceList.stream().filter(item -> (System.currentTimeMillis() - item.getLastHeartbeatTime().getTime()) <= NumberConstants.ONE_HUNDRED_EIGHTY_THOUSAND).collect(Collectors.toList());
            }
            if (deviceList == null || deviceList.isEmpty()) {
                saveRedis(mrDevice.getDeviceId().toString(), null);
                redisCache.deleteObject(ConstantsEnum.LAST_WARN_TIME.getValue() + mrDevice.getSystemId());
                update.setWarnStatus(DeviceWarnStatus.LINE.getValue());
                update.setRemark(Boolean.FALSE.toString());
            }
            mrDeviceService.updateMrDevice(update);
            associatedAlarm(mrDevice.getAssociateInternalParameters(), false);
            return;
        }
        String content = mrDevice.getSystemId() + StringConstants.COLON + mrDevice.getDeviceName() + StringConstants.UNDERSCORE + StringConstants.ALARM + StringConstants.TRIPLE_PERCENT + mrDevice.getDisplayAlarm();
        if (mrDevice.getWarnStatus().equals(DeviceWarnStatus.LINE.getValue())) {
            // 更新缓存
            redisCache.deleteObject(mrDevice.getDeviceId().toString());
            saveDeviceAlarm(mrDevice, content);
        }
        // 报警蜂鸣器输出
        buzzerOutput(mrDevice, content);
        update.setWarnStatus(DeviceWarnStatus.ALARM.getValue());
        update.setRemark(Boolean.TRUE.toString());
        mrDeviceService.updateMrDevice(update);
        associatedAlarm(mrDevice.getAssociateInternalParameters(), true);
    }

    /**
     * redis 处理
     *
     * @param key   systemId
     * @param value 报警内容
     */
    @Override
    public void saveRedis(String key, String value) {
        String dev_warn_cache = ConstantsEnum.DEV_WARN_CACHE.getValue();
        if (StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value)) {
            Map<String, String> devWarnCache = redisCache.getCacheObject(dev_warn_cache);
            if (devWarnCache == null) {
                devWarnCache = new HashMap<>();
            }
            devWarnCache.put(key, value);
            redisCache.setCacheObject(dev_warn_cache, devWarnCache);
            // 更新缓存
            redisCache.deleteObject(key);
        }
        if (StringUtils.isNotEmpty(key) && StringUtils.isEmpty(value)) {
            Map<String, String> devWarnCache = redisCache.getCacheObject(dev_warn_cache);
            if (devWarnCache != null && !devWarnCache.isEmpty() && devWarnCache.containsKey(key)) {
                devWarnCache.remove(key);
                redisCache.setCacheObject(dev_warn_cache, devWarnCache);
            }
        }
    }

    /**
     * 报警蜂鸣器输出
     *
     * @param mr      设备信息
     * @param content 报警内容
     */
    @Override
    public void buzzerOutput(MrDevice mr, String content) {
        if (mr.getWarnStatus().equals(DeviceWarnStatus.LINE.getValue())) {
            boolean f = true;
            List<SysDictData> sysDictDatas = sysDictDataService.selectDictDataByType(ConstantsEnum.ALARM_SHIELDING.getValue());
            for (SysDictData sysDictData : sysDictDatas) {
                if (ConstantsEnum.TEST_LIGHT.getValue().equals(sysDictData.getDictLabel()) && mr.getSystemId().equals(sysDictData.getDictValue())) {
                    mrDeviceService.mute(true, MaritimeConstants.BUZZER);
                }
                if (mr.getSystemId().equals(sysDictData.getDictValue())) {
                    f = false;
                }
            }
            // 报警蜂鸣器输出
            if (f) {
                // 更新缓存
                redisCache.deleteObject(mr.getDeviceId().toString());
                // redis 处理
                saveRedis(mr.getDeviceId().toString(), content);
                redisCache.setCacheObject(ConstantsEnum.LAST_WARN_TIME.getValue() + mr.getSystemId(), new Date().getTime());
                if (StringUtils.isNotEmpty(mr.getDisplayAlarm()) && DigitStringConstants.TWO.equals(mr.getDisplayAlarm())) {
                    mrDeviceService.mute(true, MaritimeConstants.BUZZER);
                }
            }
            String marine_engineer_status = ConstantsEnum.MARINE_ENGINEER_STATUS.getValue();
            redisCache.setCacheObject(marine_engineer_status, true);
        }
    }

    /**
     * 通道报警
     *
     * @param port 通道端口
     */
    @Override
    public void channelAlarm(int port) {
        MrDevice mrDevice = mrDeviceService.getDeviceByOutputSource(String.valueOf(port));
        if (mrDevice == null) {
            return;
        }
        MrDevice mrDevice1 = new MrDevice();
        mrDevice1.setDeviceId(mrDevice.getDeviceId());
        mrDevice1.setWarnStatus(DeviceWarnStatus.ALARM.getValue());
        mrDevice1.setLastHeartbeatTime(new Date());
        mrDevice1.setRemark(Boolean.TRUE.toString());
        String label = sysDictDataService.selectDictLabel(ConstantsEnum.DEVICE_SHOW_ALARM.getValue(), mrDevice.getDisplayAlarm());
        String content = mrDevice.getSystemId() + StringConstants.COLON + mrDevice.getDeviceName() + StringConstants.UNDERSCORE + mrDevice.getOutputSource() + StringConstants.CHANNEL + label + StringConstants.TRIPLE_PERCENT + mrDevice.getDisplayAlarm();
        if (mrDevice.getWarnStatus().equals(DeviceWarnStatus.LINE.getValue())) {
            // 延时时间检查
            if (shouldSkipByDelayTime(mrDevice, NumberConstants.FIVE)) {
                return;
            }
            String type = "channelAlarm";
            saveDeviceAlarmProcess(mrDevice, content, type);
        }
        mrDeviceService.updateMrDevice(mrDevice1);
        // 关联报警
        associatedAlarm(mrDevice.getAssociateInternalParameters(), true);
    }

    @Override
    public String checkThresholdAlarm(Domain domain, MrDevice mrDevice) {
        String alarmContent = null;
        // 上限报警检查
        String alarmLevel = AlarmType.TOP_LIMIT.getAlarmLevel();
        String limitType = mrDevice.getTopLimit();
        String limitDeviceRunStatus = mrDevice.getTopLimitDeviceRunStatus();
        String limitControl = mrDevice.getTopLimitControl();
        String limitAlarm = mrDevice.getTopLimitAlarm();

        alarmContent = getAlarmContent(domain, limitType, limitDeviceRunStatus, alarmContent, alarmLevel, limitControl, limitAlarm);

        // 上上限报警检查
        alarmLevel = AlarmType.UPPER_LIMIT.getAlarmLevel();
        limitType = mrDevice.getUpperLimit();
        limitDeviceRunStatus = mrDevice.getUpperLimitDeviceRunStatus();
        limitControl = mrDevice.getUpperLimitControl();
        limitAlarm = mrDevice.getUpperLimitAlarm();

        alarmContent = getAlarmContent(domain, limitType, limitDeviceRunStatus, alarmContent, alarmLevel, limitControl, limitAlarm);

        // 下限报警检查
        alarmLevel = AlarmType.LOWER_LIMIT.getAlarmLevel();
        limitType = mrDevice.getLowerLimit();
        limitDeviceRunStatus = mrDevice.getLowerLimitDeviceRunStatus();
        limitControl = mrDevice.getLowerLimitControl();
        limitAlarm = mrDevice.getLowerLimitAlarm();

        alarmContent = getAlarmContent(domain, limitType, limitDeviceRunStatus, alarmContent, alarmLevel, limitControl, limitAlarm);

        // 下下限报警检查
        alarmLevel = AlarmType.FLOOR_LIMIT.getAlarmLevel();
        limitType = mrDevice.getFloorLimit();
        limitDeviceRunStatus = mrDevice.getFloorLimitDeviceRunStatus();
        limitControl = mrDevice.getFloorLimitControl();
        limitAlarm = mrDevice.getFloorLimitAlarm();

        alarmContent = getAlarmContent(domain, limitType, limitDeviceRunStatus, alarmContent, alarmLevel, limitControl, limitAlarm);

        // 设备配置报警
        if (mrDevice.getProduct().equals(ProductEnum.TYPE_CONFIGURATION.getValue())) {
            if (StringUtils.isNotEmpty(domain.getValue()) && mrDevice.getDisplayAlarm().equals(DigitStringConstants.TWO)) {
                alarmContent = mrDevice.getRemark();
            }
        }

        return alarmContent;
    }

    private String getAlarmContent(Domain domain, String limitType, String limitDeviceRunStatus, String alarmContent, String alarmLevel, String limitControl, String limitAlarm) {
        if (StringUtils.isNotEmpty(limitType)) {
            boolean topLimitAlarm;
            if (AlarmType.TOP_LIMIT.getAlarmLevel().equals(alarmLevel) || AlarmType.UPPER_LIMIT.getAlarmLevel().equals(alarmLevel)) {
                topLimitAlarm = checkUpperThreshold(domain, limitType, limitDeviceRunStatus);
            } else {
                topLimitAlarm = checkLowerThreshold(domain, limitType, limitDeviceRunStatus);
            }
            if (topLimitAlarm) {
                alarmContent = alarmLevel;
            }
            // 1 吸合 2 复位
            if (StringUtils.isNotEmpty(limitControl)) {
                if (topLimitAlarm) {
                    if (DigitStringConstants.ONE.equals(limitControl)) {
                        mrDeviceService.muteBySystemId(true, limitAlarm);
                    }
                    if (DigitStringConstants.TWO.equals(limitControl)) {
                        mrDeviceService.muteBySystemId(false, limitAlarm);
                        return null;
                    }
                }
            }
            associatedAlarm(limitAlarm, topLimitAlarm);
        }
        return alarmContent;
    }

    @Override
    public void dataUpload(Domain domain, List<MrMonitorDevicePointValue> mrMonitorDevicePointValues, List<MrDeviceAlarmData> mrDeviceAlarmDatas, List<MrDevice> mrDeviceList) {
        MrDevice mrDevice = mrDeviceService.getDeviceBySystemId(domain.getPoint_code());
        if (mrDevice == null) {
            log.error("【dataUpload】无此设备数据，systemId: {}", domain.getPoint_code());
            return;
        }
        MrDevice update = new MrDevice();
        update.setDeviceId(mrDevice.getDeviceId());
        update.setLastHeartbeatTime(new Date());
        if (mrDevice.getUnit() == null) {
            update.setUnit(StringConstants.SPACE);
        }
        String alarmContent = "";
        boolean flag = false;
        if (mrDevice.getModality().equals(ProductEnum.BA.getValue())) {
            alarmContent = checkThresholdAlarm(domain, mrDevice);
            if (alarmContent != null) {
                flag = true;
            }
        } else {
            flag = DigitStringConstants.ONE.equals(domain.getValue());
            // 判断是闭合报警还是断开报警
            if (StringUtils.isNotEmpty(mrDevice.getDataDefinition()) && mrDevice.getDataDefinition().equals(DigitStringConstants.ZERO)) {
                flag = !flag;
            }
            // 开关量关联设备运行状态
            if (flag && StringUtils.isNotEmpty(mrDevice.getMrDeviceRunStatus())) {
                MrDevice mrDevice1 = mrDeviceService.getDeviceBySystemId(mrDevice.getMrDeviceRunStatus());
                flag = mrDevice1 != null && DeviceStatus.ACTIVE.getValue().equals(mrDevice1.getStatus()) && DeviceWarnStatus.ALARM.getValue().equals(mrDevice1.getWarnStatus());
            }
            domain.setValue(String.valueOf(flag));
        }
        extracted(domain, mrMonitorDevicePointValues, mrDevice);
        if (!flag) {
            update.setWarnStatus(DeviceWarnStatus.LINE.getValue());
            update.setRemark(domain.getValue());
            // redis 处理
            saveRedis(mrDevice.getDeviceId().toString(), null);
            redisCache.deleteObject(ConstantsEnum.LAST_WARN_TIME.getValue() + mrDevice.getSystemId());
        } else {
            // 延时时间检查
            if (shouldSkipByDelayTime(mrDevice, 0)) {
                mrDeviceService.updateMrDevice(update);
                return;
            }
            String content = "";
            if (mrDevice.getWarnStatus().equals(DeviceWarnStatus.LINE.getValue())) {
                content = processAlarmData(mrDevice, domain, alarmContent, mrDeviceAlarmDatas);
                // 报警轮机员输出
                marineEngineer(mrDevice.getSystemId(), "dataUpload");
                // 记录报警时间
                redisCache.setCacheObject(ConstantsEnum.LAST_WARN_TIME.getValue() + mrDevice.getSystemId(), new Date().getTime());

            } else if (mrDevice.getWarnStatus().equals(DeviceWarnStatus.ALARM.getValue())) {
                String alarmContentOld = redisCache.getCacheObject(ConstantsEnum.DEVICE_WARN_COUNT.getValue() + mrDevice.getSystemId());
                if (alarmContentOld != null) {
                    if (!alarmContent.equals(alarmContentOld)) {
                        content = processAlarmData(mrDevice, domain, alarmContent, mrDeviceAlarmDatas);
                    }
                } else {
                    // 记录报警信息
                    redisCache.setCacheObject(ConstantsEnum.DEVICE_WARN_COUNT.getValue() + mrDevice.getSystemId(), alarmContent);
                }
            }
            // 报警蜂鸣器输出
            buzzerOutput(mrDevice, content);
            update.setWarnStatus(DeviceWarnStatus.ALARM.getValue());
            update.setRemark(domain.getValue());
        }
        mrDeviceList.add(update);
        mrDeviceService.updateMrDevice(update);
        // 关联报警
        associatedAlarm(mrDevice.getAssociateInternalParameters(), flag);
    }

    private static void extracted(Domain domain, List<MrMonitorDevicePointValue> mrMonitorDevicePointValues, MrDevice mrDevice) {
        //记录数据
        MrMonitorDevicePointValue mrMonitorDevicePointValue = new MrMonitorDevicePointValue();
        mrMonitorDevicePointValue.setOriginMsg(domain.getValue());
        mrMonitorDevicePointValue.setPointCode(mrDevice.getUnit());
        mrMonitorDevicePointValue.setBoxCode(mrDevice.getSystemId());
        mrMonitorDevicePointValue.setMetricTime(new Date());
        mrMonitorDevicePointValue.setReportTime(new Date());
        mrMonitorDevicePointValues.add(mrMonitorDevicePointValue);
    }

    @Override
    public void processGatewayUpstreamData(JSONObject jsonObject) {
        // 1.参数校验
        if (validateJSONObject(jsonObject)) return;

        // 2.数据获取
        List<Domain> domainList = getDomainList(jsonObject);

        // 3.数据处理
        dataProcessing(domainList);

    }

    @Override
    public void dataProcessing(List<Domain> domainList) {
        // 上行数据
        List<MrMonitorDevicePointValue> mrMonitorDevicePointValues = new ArrayList<>();
        // 报警数据
        List<MrDeviceAlarmData> mrDeviceAlarmDatas = new ArrayList<>();
        // 设备信息
        List<MrDevice> mrDeviceList = new ArrayList<>();
        for (Domain domain : domainList) {
            // 上行数据报警处理
            dataUpload(domain, mrMonitorDevicePointValues, mrDeviceAlarmDatas, mrDeviceList);
            // 更新通道状态
            updateDeviceStatus(domain.getPort());
        }
        // 保存数据
        gatewayBatchData(mrMonitorDevicePointValues, mrDeviceAlarmDatas, mrDeviceList);
    }

    private List<Domain> getDomainList(JSONObject jsonObject) {
        List<Domain> domainList = new ArrayList<>();
        // 获取设备信息
        MrDevice mrDevice = new MrDevice();
        mrDevice.setStatus(DeviceStatus.ACTIVE.getValue());
        if (jsonObject.containsKey(ConstantsEnum.SLAVE_ADD.getValue())) {
            mrDevice.setHospitalNumber(jsonObject.getString(ConstantsEnum.SLAVE_ADD.getValue()));
        }
        // 功能码处理
        processFunctionCode(jsonObject, mrDevice);
        String port = jsonObject.getString(ConstantsEnum.DEV_PORT.getValue());
        mrDevice.setPort(port);
        List<MrDevice> mrDevices = mrDeviceService.selectMrDeviceList(mrDevice);
        for (MrDevice mr : mrDevices) {
            Domain domain = new Domain();
            domain.setPoint_code(mr.getSystemId());
            domain.setPort(port);
            String value = null;

            if (validateProduct(mr)) {
                mr.setRegisData(jsonObject.getString(ConstantsEnum.REGIS_DATA.getValue()));
            } else {
                Integer startAdd = jsonObject.getInteger(ConstantsEnum.START_ADD.getValue());
                List<String> regisData = jsonObject.getList(ConstantsEnum.REGIS_DATA.getValue(), String.class);
                mr.setStartAdd(startAdd);
                mr.setRegisDatas(regisData);
                // 参数校验
                if (!validateDeviceParameters(regisData, startAdd, mr, jsonObject)) {
                    continue;
                }
                // 双寄存器处理
                try {
                    value = processRegisterValue(mr.getRegisterAddress(), startAdd, regisData, mr.getSystemId(), jsonObject);
                } catch (RegisterProcessingException e) {
                    String msg = "【dataUpload】【getDomainList】寄存器处理失败: " + e.getMessage() + "，设备ID: " + mr.getSystemId() + "，数据: " + jsonObject;
                    logUtil.warn(ClassMethodNameUtil.getSimpleMethodName(), msg);
                    continue;
                }
            }
            // 网关数据协议处理
            value = processData(mr, value);
            if (StringUtils.isNotEmpty(value)) {
                domain.setValue(value);
                domainList.add(domain);
            }
        }
        return domainList;
    }

    private boolean validateProduct(MrDevice mr) {
        if (mr.getProduct().equals(ProductEnum.TYPE_0183_VDR.getValue())) {
            return true;
        }
        if (mr.getProduct().equals(ProductEnum.TYPE_0183.getValue())) {
            return true;
        }
        if (mr.getProduct().equals(ProductEnum.TYPE_LDAXDR.getValue())) {
            return true;
        }
        if (mr.getProduct().equals(ProductEnum.TYPE_XDR.getValue())) {
            return true;
        }
        if (mr.getProduct().equals(ProductEnum.TYPE_HXALA.getValue())) {
            return true;
        }
        return false;
    }

    private boolean validateJSONObject(JSONObject jsonObject) {
        if (jsonObject.isEmpty()) {
            return true;
        }
        if (checkConnect()) {
            return true;
        }
        // 通道报警
        if (jsonObject.containsKey(ConstantsEnum.DATA_STATUS.getValue()) && jsonObject.getString(ConstantsEnum.DATA_STATUS.getValue()).equals(DigitStringConstants.NEGATIVE_ONE)) {
            channelAlarm(jsonObject.getInteger(ConstantsEnum.DEV_PORT.getValue()));
            return true;
        }
        return !jsonObject.containsKey(ConstantsEnum.DEV_PORT.getValue());
    }

    /**
     * 网关下发配置
     *
     * @param devSn 网关设备的dev_sn
     * @return 网关配置
     */
    @Override
    public JSONObject configuration(String devSn) {
        if (StringUtils.isEmpty(devSn)) {
            log.warn("{}devSn不能为空", GatewayConfigConstants.Log.PREFIX);
            return createErrorResponse(GatewayConfigConstants.Error.EMPTY_DEV_SN);
        }

        try {
            List<MrBed> mrBeds = mrBedService.selectMrBedByDevSn(devSn);
            if (CollectionUtils.isEmpty(mrBeds)) {
                log.warn("{}未配置设备 - devSn: {}", GatewayConfigConstants.Log.PREFIX, devSn);
                return createErrorResponse(GatewayConfigConstants.Error.DEVICE_NOT_CONFIGURED);
            }

            // 批量预加载协议配置
            Set<String> allProtocolIds = collectAllProtocolIds(mrBeds);
            Map<Long, MrDeviceProtocolConfiguration> protocolConfigMap = loadProtocolConfigurations(allProtocolIds);

            JSONObject result = new JSONObject();
            List<Map<String, Object>> upPorts = new ArrayList<>(mrBeds.size());
            List<Map<String, Integer>> downPorts = new ArrayList<>(mrBeds.size());

            for (MrBed mrBed : mrBeds) {
                processSingleBed(mrBed, protocolConfigMap, upPorts, downPorts);
            }

            result.put(GatewayConfigConstants.Key.UP_PORTS, upPorts);
            result.put(GatewayConfigConstants.Key.DOWN_PORTS, downPorts);
            return result;
        } catch (Exception e) {
            log.error("{}配置生成失败 - devSn: {}", GatewayConfigConstants.Log.PREFIX, devSn, e);
            return createErrorResponse(e.getMessage());
        }
    }

    // 收集所有协议ID（批量查询优化）
    private Set<String> collectAllProtocolIds(List<MrBed> mrBeds) {
        return mrBeds.stream().filter(bed -> StringUtils.isNotEmpty(bed.getGatewayProtocol()))
                .flatMap(bed -> Arrays.stream(bed.getGatewayProtocol().split(StringConstants.COMMA))).collect(Collectors.toSet());
    }

    // 批量加载协议配置
    private Map<Long, MrDeviceProtocolConfiguration> loadProtocolConfigurations(Set<String> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyMap();
        }

        List<MrDeviceProtocolConfiguration> configs = mrDeviceProtocolConfigurationService.selectMrDeviceProtocolConfigurationByIds(ids.toArray(new String[0]));

        return configs.stream().collect(Collectors.toMap(MrDeviceProtocolConfiguration::getId, Function.identity(), (existing, replacement) -> existing));
    }

    // 处理单个床位配置
    private void processSingleBed(MrBed mrBed,
                                  Map<Long, MrDeviceProtocolConfiguration> protocolConfigMap,
                                  List<Map<String, Object>> upPorts,
                                  List<Map<String, Integer>> downPorts) {
        String[] protocolIds = mrBed.getGatewayProtocol().split(StringConstants.COMMA);
        Map<String, Object> upPortMap = new HashMap<>(NumberConstants.EIGHT);
        List<Map<String, Integer>> dataList = new ArrayList<>();
        Map<String, Integer> downPortMap = new HashMap<>(NumberConstants.EIGHT);
        for (String protocolId : protocolIds) {
            MrDeviceProtocolConfiguration config = protocolConfigMap.get(Long.parseLong(protocolId));
            if (config == null) {
                log.warn(GatewayConfigConstants.Log.WARN_PROTOCOL_MISSING, GatewayConfigConstants.Log.PREFIX, protocolId);
                continue;
            }
            if (ProductEnum.BA.getValue().equals(config.getProtocolType())) {
                buildDownPortConfig(mrBed, config, downPortMap);
            } else {
                buildUpPortConfig(mrBed, config, upPortMap, dataList);
            }
        }
        if (!dataList.isEmpty()) {
            upPortMap.put(GatewayConfigConstants.Key.DATA, dataList);
        }
        if (!upPortMap.isEmpty()) {
            upPorts.add(upPortMap);
        }
        if (!downPortMap.isEmpty()) {
            downPorts.add(downPortMap);
        }
    }

    // 构建下行端口配置
    private void buildDownPortConfig(MrBed mrBed,
                                     MrDeviceProtocolConfiguration config,
                                     Map<String, Integer> downPortMap) {
        safePut(downPortMap, GatewayConfigConstants.Key.SERIAL_PORT, mrBed.getSerialPort());
        safePut(downPortMap, GatewayConfigConstants.Key.BAUDRATE, config.getBaud());
        safePut(downPortMap, GatewayConfigConstants.Key.DEV_PORT, mrBed.getBedName());
        safePut(downPortMap, GatewayConfigConstants.Key.LISTEN_PORT, config.getListenPort());
        safePut(downPortMap, GatewayConfigConstants.Key.TRANS_FLAG, config.getRegisterBit());
    }

    // 构建上行端口配置
    private void buildUpPortConfig(MrBed mrBed,
                                   MrDeviceProtocolConfiguration config,
                                   Map<String, Object> upPortMap,
                                   List<Map<String, Integer>> dataList) {
        safePutObject(upPortMap, GatewayConfigConstants.Key.SERIAL_PORT, mrBed.getSerialPort());
        safePutObject(upPortMap, GatewayConfigConstants.Key.BAUDRATE, config.getBaud());
        safePutObject(upPortMap, GatewayConfigConstants.Key.DEV_PORT, mrBed.getBedName());
        safePutObject(upPortMap, GatewayConfigConstants.Key.PARITY_CHECK, config.getCheckBit());
        safePutObject(upPortMap, GatewayConfigConstants.Key.TRANS_FLAG, config.getRegisterBit());

        Map<String, Integer> dataMap = new HashMap<>(NumberConstants.EIGHT);
        safePut(dataMap, GatewayConfigConstants.Key.Data.SLAVE_ADDR, config.getAddressCode());
        safePut(dataMap, GatewayConfigConstants.Key.Data.FUNC_CODE, config.getFunctionCode());
        safePut(dataMap, GatewayConfigConstants.Key.Data.REG_NUM, config.getRegisterNumber());
        safePut(dataMap, GatewayConfigConstants.Key.Data.START_ADDR, config.getStartAddr());
        dataList.add(dataMap);
    }

    // 安全数值转换方法
    private void safePutObject(Map<String, Object> map, String key, String value) {
        try {
            if (StringUtils.isNumeric(value)) {
                map.put(key, Integer.parseInt(value));
            }
        } catch (NumberFormatException e) {
            log.warn(GatewayConfigConstants.Log.WARN_NUM_CONVERSION, GatewayConfigConstants.Log.PREFIX, key, value);
        }
    }

    private void safePut(Map<String, Integer> map, String key, String value) {
        try {
            if (StringUtils.isNumeric(value)) {
                map.put(key, Integer.parseInt(value));
            }
        } catch (NumberFormatException e) {
            log.warn(GatewayConfigConstants.Log.WARN_NUM_CONVERSION, GatewayConfigConstants.Log.PREFIX, key, value);
        }
    }

    // 创建错误响应
    private JSONObject createErrorResponse(String message) {
        JSONObject error = new JSONObject();
        error.put("error", true);
        error.put("message", message);
        return error;
    }

    /**
     * 组装报警数据
     *
     * @param mrDevice     设备信息
     * @param domain       数据域
     * @param alarmContent 报警内容
     */
    public String processAlarmData(MrDevice mrDevice, Domain domain, String alarmContent, List<MrDeviceAlarmData> alarmDatas) {
        MrDeviceAlarmData alarmData = new MrDeviceAlarmData();

        // 获取字典标签
        String label = getDictLabel(mrDevice);

        // 构建报警内容
        String content = buildAlarmContent(mrDevice, domain, alarmContent, label);

        // 设置公共属性
        setCommonProperties(alarmData, mrDevice, content);

        // 添加到结果列表
        alarmDatas.add(alarmData);

        // 记录报警计数到Redis
        redisCache.setCacheObject(ConstantsEnum.DEVICE_WARN_COUNT.getValue() + mrDevice.getSystemId(), alarmContent);

        return content;
    }

    private String getDictLabel(MrDevice mrDevice) {
        return StringUtils.isNotEmpty(mrDevice.getDisplayAlarm())
                ? sysDictDataService.selectDictLabel(ConstantsEnum.DEVICE_SHOW_ALARM.getValue(), mrDevice.getDisplayAlarm())
                : "";
    }

    private String buildAlarmContent(MrDevice mrDevice, Domain domain, String alarmContent, String label) {
        if (ProductEnum.BA.getValue().equals(mrDevice.getModality())) {
            return mrDevice.getSystemId() + StringConstants.COLON + mrDevice.getDeviceName() + StringConstants.UNDERSCORE + StringConstants.SPACE +
                    alarmContent + label + StringConstants.COMMA + StringConstants.VALUE_IS + StringConstants.COLON + domain.getValue() + StringConstants.TRIPLE_PERCENT + mrDevice.getDisplayAlarm();
        } else {
            return mrDevice.getSystemId() + StringConstants.COLON + mrDevice.getDeviceName() + StringConstants.UNDERSCORE + StringConstants.COMMA +
                    mrDevice.getLightColor() + StringConstants.LIGHT + StringConstants.TRIPLE_PERCENT + mrDevice.getDisplayAlarm();
        }
    }

    private void setCommonProperties(MrDeviceAlarmData alarmData, MrDevice mrDevice, String content) {
        alarmData.setAlarmTime(new Date());
        alarmData.setDeviceCode(mrDevice.getSystemId());
        alarmData.setDeviceName(mrDevice.getDeviceName());
        alarmData.setContent(content.split(StringConstants.TRIPLE_PERCENT)[0]);
        alarmData.setId(UUID.randomUUID().toString());
        alarmData.setDisplayAlarm(mrDevice.getDisplayAlarm());
        alarmData.setUnit(ProductEnum.BA.getValue().equals(mrDevice.getModality()) ? mrDevice.getUnit() : StringConstants.KILOGRAM);
    }

    /**
     * {"device_ip":"192.168.1.88","timestamp":"707711","interfaces":[{"name":"eth0","status":"up"},{"name":"eth1","status":"down"}]}
     *
     * @param jsonObject 网关心跳
     */
    @Override
    public void heartbeatDetection(JSONObject jsonObject) {
        String deviceIp = jsonObject.getString(HeartbeatDetectionConstants.DEVICE_IP);
        JSONArray interfaces = jsonObject.getJSONArray(HeartbeatDetectionConstants.INTERFACES);
        interfaces.forEach(item -> {
            JSONObject obj = new JSONObject((Map<?, ?>) item);
            String key = deviceIp + obj.getString(HeartbeatDetectionConstants.NAME);
            String status = obj.getString(HeartbeatDetectionConstants.STATUS);
            boolean flag = status.contains(HeartbeatDetectionConstants.DOWN);
            String systemId = sysDictDataService.selectDictValue(HeartbeatDetectionConstants.GATEWAY_HEARTBEAT_CONFIGURATION, key);
            extracted(systemId, flag);
        });

    }

    private void extracted(String systemId, boolean flag) {
        MrDevice mr = mrDeviceService.getDeviceBySystemId(systemId);
        if (mr == null) {
            return;
        }
        Long deviceId = mr.getDeviceId();
        MrDevice mrDev = new MrDevice();
        mrDev.setDeviceId(deviceId);
        mrDev.setRemark(String.valueOf(flag));
        // 设备报警
        if (flag) {
            redisCache.setCacheObject(ConstantsEnum.MONITORING_ALARM_SYSTEM.getValue(), false);
            if (!mr.getWarnStatus().equals(DeviceWarnStatus.ALARM.getValue())) {
                // 延时时间
                if (!shouldSkipByDelayTime(mr, NumberConstants.FIVE)) {
                    // 更新数据库设备告警状态
                    mrDev.setWarnStatus(DeviceWarnStatus.ALARM.getValue());
                    String content = mr.getSystemId() + StringConstants.COLON + mr.getDeviceName() + StringConstants.UNDERSCORE + StringConstants.DEVICE_ALARM + StringConstants.TRIPLE_PERCENT + mr.getDisplayAlarm();
                    redisCache.setCacheObject(ConstantsEnum.MARINE_ENGINEER_STATUS.getValue(), true);
                    String type = "networkCheck";

                    saveDeviceAlarmProcess(mr, content, type);
                }
            }
        } else {
            // 更新数据库设备告警状态
            mrDev.setWarnStatus(DeviceWarnStatus.LINE.getValue());
            // redis 处理
            saveRedis(deviceId.toString(), null);
            redisCache.setCacheObject(CacheConstants.DEV_WARN_CACHE + mr.getSystemId(), 0);
            redisCache.deleteObject(ConstantsEnum.LAST_WARN_TIME.getValue() + mr.getSystemId());
        }
        mrDev.setLastHeartbeatTime(new Date());
        mrDeviceService.updateMrDevice(mrDev);
        // 关联报警
        associatedAlarm(mr.getAssociateInternalParameters(), flag);
    }

    private void saveDeviceAlarmProcess(MrDevice mr, String content, String type) {
        saveDeviceAlarm(mr, content);
        // 报警蜂鸣器输出
        mrDeviceService.mute(true, MaritimeConstants.BUZZER);
        // 报警轮机员输出
        marineEngineer(mr.getSystemId(), type);
    }

    private void saveDeviceAlarm(MrDevice mr, String content) {
        MrDeviceAlarmData mrDeviceAlarmData = new MrDeviceAlarmData();
        mrDeviceAlarmData.setUnit(StringUtils.isEmpty(mr.getUnit()) ? StringConstants.KILOGRAM : mr.getUnit());
        mrDeviceAlarmData.setAlarmTime(new Date());
        mrDeviceAlarmData.setDeviceCode(mr.getSystemId());
        mrDeviceAlarmData.setDeviceName(mr.getDeviceName());
        mrDeviceAlarmData.setContent(content.split(StringConstants.TRIPLE_PERCENT)[0]);
        mrDeviceAlarmData.setDisplayAlarm(mr.getDisplayAlarm());
        mrDeviceAlarmDataService.insertMrDeviceAlarmData(mrDeviceAlarmData);
        // redis 处理
        saveRedis(mr.getDeviceId().toString(), content);
        redisCache.setCacheObject(ConstantsEnum.LAST_WARN_TIME.getValue() + mr.getSystemId(), System.currentTimeMillis());
    }


    /**
     * 检查上限阈值
     */
    private boolean checkUpperThreshold(Domain domain, String limitValue, String deviceRunStatusId) {
        if (domain.getValue() == null) {
            return false;
        }
        double currentValue = Double.parseDouble(domain.getValue());
        double threshold = Double.parseDouble(limitValue);
        if (currentValue >= threshold) {
            if (StringUtils.isNotEmpty(deviceRunStatusId)) {
                MrDevice statusDevice = mrDeviceService.getDeviceBySystemId(deviceRunStatusId);
                return statusDevice != null && DeviceStatus.ACTIVE.getValue().equals(statusDevice.getStatus())
                        && DeviceWarnStatus.ALARM.getValue().equals(statusDevice.getWarnStatus());
            }
            return true;
        }
        return false;
    }

    /**
     * 检查下限阈值
     */
    private boolean checkLowerThreshold(Domain domain, String limitValue, String deviceRunStatusId) {
        if (domain.getValue() == null) {
            return false;
        }
        double currentValue = Double.parseDouble(domain.getValue());
        double threshold = Double.parseDouble(limitValue);
        if (currentValue <= threshold) {
            if (StringUtils.isNotEmpty(deviceRunStatusId)) {
                MrDevice statusDevice = mrDeviceService.getDeviceBySystemId(deviceRunStatusId);
                return statusDevice != null && DeviceStatus.ACTIVE.getValue().equals(statusDevice.getStatus())
                        && DeviceWarnStatus.ALARM.getValue().equals(statusDevice.getWarnStatus());
            }
            return true;
        }
        return false;
    }

    @Override
    public char[] getChars(String value) {
        try {
            // 将传入的字符串转换为整数，再转换为二进制字符串
            String binaryNumber = Integer.toBinaryString(Integer.parseInt(value));
            // 创建 StringBuilder 对象并赋值为原始二进制字符串
            StringBuilder sb = new StringBuilder(binaryNumber);
            // 反转二进制字符串
            sb.reverse();
            // 调用补零方法，确保字符串长度为 16 位
            padWithZeros(sb);
            // 将处理后的字符串转换为字符数组并返回
            return sb.toString().toCharArray();
        } catch (NumberFormatException e) {
            // 处理传入的字符串不是有效整数格式的异常
            log.error("【getChars】传入的字符串不是有效的整数格式: {}", value);
            return new char[0];
        }
    }

    /**
     * 补零方法，确保 StringBuilder 的长度达到指定长度
     *
     * @param sb StringBuilder 对象
     */
    private static void padWithZeros(StringBuilder sb) {
        while (sb.length() < NumberConstants.SIXTEEN) {
            sb.append(DigitStringConstants.ZERO);
        }
    }

}
